/*
--------------------------------------------------------------------------------
				Ak-Lib. 
			 Project       	: Ak-Lib
			 Group         	: Ak-Lib R&D Team
			 Author        	: Ocean.Wang
			 Create Date 	: 05-01-2010
--------------------------------------------------------------------------------
Code Name 	:  A.K 	~v~
Description	:  Yet Another Cross-Platform Lib.
Cautions    	:
--------------------------------------------------------------------------------
Change History:
Version		: 0.1
Building 		: 05/01/10
10-05.01 first draft, build, debug and test.
--------------------------------------------------------------------------------
*/

#include "ak_mem.h"
#include "ak_gears.h"

/* Test the Simple */
static 	_t_sysMSlot 	_gTest_MSlot_Simple;
static 	_t_sysMPool 	_gTest_MPool_Simple;
static	_t_sysMHeap 	_gTest_MHeap_Simple;

#define _TEST_MEM_PAGE_SIMPLE 		0X1000		/*  4k Based */

#define _TEST_MEM_DUMP_BUF 	0X10000
static 	char 			_gTest_MDump[_TEST_MEM_DUMP_BUF];
static 	_t_sysMi 	*	_gTest_Mi[50000];

static 	int 	_Test_Simple(int flag)
{
	int i, j, count;
	unsigned int 	mLimit;
	_t_sysMPool * pPool;
	_t_sysMHeap * pHeap;
	_t_sysMSlot * pSlot;

	_t_sysMi * 	pItem;
	_t_sysMi ** itemAU;
	_t_blist	itemQue;

	/* Init the Heap, Pool, Slot */
	pHeap = &_gTest_MHeap_Simple;
	pPool = &_gTest_MPool_Simple;
	pSlot = &_gTest_MSlot_Simple;
	itemAU= _gTest_Mi;
	
	if(flag == 0){
		mLimit = 1;
		MHeap_Init(pHeap, mLimit);
		MPool_Init(pPool, pHeap,	
					_TEST_MEM_PAGE_SIMPLE,	sizeof(_t_sysMi), 
					1,	 1,	MPOOL_T_SIMP);
	}else{
		mLimit = _TEST_MEM_PAGE_SIMPLE * 4;
		MHeap_InitEx(pHeap, mLimit);
		MPool_Init(pPool, pHeap,	
					mLimit,	sizeof(_t_sysMi), 
					1,	 1,	MPOOL_T_SIMP);
	}
	
	/* Init the Slot */
	MPOOL_SET_SLOT(pPool, pSlot);
	MSlot_Init(pSlot, pPool, 0, (unsigned int)(sizeof(_t_sysMi)));

	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 0: \n%s\n", _gTest_MDump);
	
	BLIST_INIT(&itemQue);
	for(i=0; i<20; i++){
		MPool_AllocNi(pPool, &itemQue, 10);
	}
	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 1: \n%s\n", _gTest_MDump);

	if((count =itemQue.count) > 0){
		for(j=0; j<count; j++){
			pItem = (_t_sysMi *)BLST_GET(&itemQue);
			itemAU[j] = pItem;
		}
		for(i=0; i<20; i++){
			BLIST_INIT(&itemQue);
			for(j=0; j<10; j++){
				pItem = itemAU[i*10 + j];
				BLST_ADD2T(&itemQue, &(pItem->aNode));
			}
			MPool_FreeNi(pPool, &itemQue);
		}
	}	
	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 2: \n%s\n", _gTest_MDump);

	for(i=0; i<200; i++){
		pItem = MPool_AllocSi(pPool);
		if(pItem){
			itemAU[i] = pItem;
		}else{
			itemAU[i] = NULL;
		}
	}
	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 3: \n%s\n", _gTest_MDump);

	for(i=0; i<200; i++){
		pItem = itemAU[i];
		if(itemAU[i]){
			MPool_FreeSi(pPool, pItem);
		}
	}
	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 4: \n%s\n", _gTest_MDump);

	return 0;
}

#define _TEST_MEM_SLAB 			9
#define _TEST_MEM_PAGE_SLAB 	0X10000		/*  64k Based */

static 	size_t 			_gTest_Size_Slab[_TEST_MEM_SLAB];
static 	_t_sysMSlot 	_gTest_MSlot_Slab[_TEST_MEM_SLAB];
static 	_t_sysMPool 	_gTest_MPool_Slab;
static	_t_sysMHeap 	_gTest_MHeap_Slab;

static 	int 	_Test_Slab(int alkCnt)
{
	int i, j, k, count;
	_t_sysMPool * pPool;
	_t_sysMHeap * pHeap;
	_t_sysMSlot * pSlot;
	size_t 		* pSize;
	unsigned int  mLimit;
	_t_mTiming 	  timing;
	
	_t_sysMi 	** itemAU;

	/* Init the Heap, Pool, Slot */
	pHeap = &_gTest_MHeap_Slab;
	pPool = &_gTest_MPool_Slab;
	pSlot = _gTest_MSlot_Slab;
	pSize = _gTest_Size_Slab;
	itemAU= _gTest_Mi;
	
	mLimit= 50;
	MHeap_Init(pHeap, mLimit);
	MPool_Init(pPool, pHeap, 			_TEST_MEM_PAGE_SLAB, 0X1000,		8,	32,		MPOOL_T_SLAB);
	MSlab_Init(pPool, pSlot,  pSize,  	_TEST_MEM_SLAB,	0X100,	sizeof(_t_sysMi));
	
	MPool_Pre(pPool, 0, 2);
	MPool_Pre(pPool, 1, 2);
	MPool_Pre(pPool, 2, 2);
	
	/* Check Alloc */
	if(alkCnt > 0X1000)
		alkCnt = 0X1000;
	
	STIMING_BEG(timing);
	for(i=0, count=0; i<_TEST_MEM_SLAB; i++){
		for(j=0; j<alkCnt; j++){
			itemAU[count]=MPool_Alloc(pPool, pPool->slabs[i]);
			count += 1;
		}
	}
	STIMING_END(timing);
	STIMING_PRINT(timing, "Alloc");

	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 0: \n%s\n", _gTest_MDump);
	
	/* Check Free */
	STIMING_BEG(timing);
	for(i=0; i<count; i++){
		MPool_Free(pPool, itemAU[i]);
	}
	STIMING_END(timing);
	STIMING_PRINT(timing, "Free");

	STIMING_BEG(timing);
	for(k=0; k<100; k++){
		for(i=0, count=0; i<_TEST_MEM_SLAB; i++){
			for(j=0; j<alkCnt; j++){
				itemAU[count]=MPool_Alloc(pPool, pPool->slabs[i]);
				count += 1;
			}
		}
		
		for(i=0; i<count; i++){
			MPool_Free(pPool, itemAU[i]);
		}
	}
	STIMING_END(timing);
	STIMING_PRINT(timing, "Alloc & Free");

	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 1: \n%s\n", _gTest_MDump);
	
	return 0;
}


#define _TEST_MEM_GC 			17
#define _TEST_MEM_PAGE_GC 		0X100000		/*  64k Based */

static 	size_t 			_gTest_Size_Gc[_TEST_MEM_GC];
static 	_t_sysMSlot 	_gTest_MSlot_Gc[_TEST_MEM_GC];
static 	_t_sysMPool 	_gTest_MPool_Gc;
static	_t_sysMHeap 	_gTest_MHeap_Gc;

static 	int 	_Test_Gc(int alkCnt)
{
	int i, j, k, count;
	_t_sysMPool * pPool;
	_t_sysMHeap * pHeap;
	_t_sysMSlot * pSlot;
	size_t 		* pSize;
	unsigned int  mLimit;
	_t_mTiming 	  timing;
	
	_t_sysMi 	** itemAU;

	/* Init the Heap, Pool, Slot */
	pHeap = &_gTest_MHeap_Gc;
	pPool = &_gTest_MPool_Gc;
	pSlot = _gTest_MSlot_Gc;
	pSize = _gTest_Size_Gc;
	itemAU= _gTest_Mi;

	mLimit= 250;
	MHeap_Init(pHeap, mLimit);
	MPool_Init(pPool, pHeap, 			_TEST_MEM_PAGE_GC, 0X10000,		4,	16,		MPOOL_T_SLAB_GC);
	MSlab_Init(pPool, pSlot,  pSize,  	_TEST_MEM_GC,	0X100,	sizeof(_t_sysMi));
	
	MPool_Pre(pPool, 0, 2);
	MPool_Pre(pPool, 1, 2);
	MPool_Pre(pPool, 2, 2);
	
	/* Check Alloc */
	STIMING_BEG(timing);
	for(i=0, count=0; i<_TEST_MEM_GC; i++){
		for(j=0; j<alkCnt; j++){
			itemAU[count]=MPool_AllocEx(pPool, pPool->slabs[i]);
			count += 1;
		}
	}
	STIMING_END(timing);
	STIMING_PRINT(timing, "Alloc");
	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 0: \n%s\n", _gTest_MDump);

	
	/* Check Free */
	STIMING_BEG(timing);
	for(i=0; i<count; i++){
		MPool_FreeEx(pPool, itemAU[i]);
	}
	STIMING_END(timing);
	STIMING_PRINT(timing, "Free");
	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 1: \n%s\n", _gTest_MDump);


	STIMING_BEG(timing);
	for(k=0; k<100; k++){
		for(i=0, count=0; i<_TEST_MEM_GC; i++){
			for(j=0; j<alkCnt; j++){
				itemAU[count]=MPool_AllocEx(pPool, pPool->slabs[i]);
				count += 1;
			}
		}
		
		for(i=0; i<count; i++){
			MPool_FreeEx(pPool, itemAU[i]);
		}
	}
	STIMING_END(timing);
	STIMING_PRINT(timing, "Alloc & Free");
	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 2: \n%s\n", _gTest_MDump);

	
	/* Check GC */
	STIMING_BEG(timing);
	MPool_GC(pPool, 50);

	STIMING_END(timing);
	STIMING_PRINT(timing, "GC");
	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 3: \n%s\n", _gTest_MDump);

	STIMING_BEG(timing);
	for(k=0; k<100; k++){
		for(i=0, count=0; i<_TEST_MEM_GC; i++){
			for(j=0; j<alkCnt; j++){
				itemAU[count]=MPool_AllocEx(pPool, pPool->slabs[i]);
				count += 1;
			}
		}
		
		for(i=0; i<count; i++){
			MPool_FreeEx(pPool, itemAU[i]);
		}
	}
	STIMING_END(timing);
	STIMING_PRINT(timing, "Alloc & Free");
	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 4: \n%s\n", _gTest_MDump);

	
	return 0;
}


#define _TEST_MEM_GN 			7
#define _TEST_MEM_PAGE_GN 		0X400000		/*  64k Based */

static 	size_t 			_gTest_Size_Gn[_TEST_MEM_GN];
static 	_t_sysMSlot 	_gTest_MSlot_Gn[_TEST_MEM_GN];
static 	_t_sysMPool 	_gTest_MPool_Gn;
static	_t_sysMHeap 	_gTest_MHeap_Gn;

static 	int 	_Test_Gn(int alkCnt)
{
	int i, j, k, count;
	_t_sysMPool * pPool;
	_t_sysMHeap * pHeap;
	_t_sysMSlot * pSlot;
	size_t 		* pSize;
	unsigned int  mLimit;
	_t_mTiming 	  timing;
	
	_t_sysMi 	** itemAU;

	/* Init the Heap, Pool, Slot */
	pHeap = &_gTest_MHeap_Gn;
	pPool = &_gTest_MPool_Gn;
	pSlot = _gTest_MSlot_Gn;
	pSize = _gTest_Size_Gn;
	itemAU= _gTest_Mi;

	mLimit= 350;
	MHeap_Init(pHeap, mLimit);
	MPool_Init(pPool, pHeap, 			_TEST_MEM_PAGE_GN, 0X100000,		4,	16,		MPOOL_T_SLAB_GN);
	MSlab_Init(pPool, pSlot,  pSize,  	_TEST_MEM_GN,	0X20000,	sizeof(_t_sysMi));
	
	MPool_Pre(pPool, 0, 2);
	MPool_Pre(pPool, 1, 2);
	MPool_Pre(pPool, 2, 2);
	
	/* Check Alloc */
	STIMING_BEG(timing);
	for(i=0, count=0; i<_TEST_MEM_GN; i++){
		for(j=0; j<alkCnt; j++){
			itemAU[count]=MPool_AllocEx(pPool, pPool->slabs[i]);
			count += 1;
		}
	}
	STIMING_END(timing);
	STIMING_PRINT(timing, "Alloc");
	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 0: \n%s\n", _gTest_MDump);

	
	/* Check Free */
	STIMING_BEG(timing);
	for(i=0; i<count; i++){
		MPool_FreeEx(pPool, itemAU[i]);
	}
	STIMING_END(timing);
	STIMING_PRINT(timing, "Free");
	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 1: \n%s\n", _gTest_MDump);


	STIMING_BEG(timing);
	for(k=0; k<100; k++){
		for(i=0, count=0; i<_TEST_MEM_GN; i++){
			for(j=0; j<alkCnt; j++){
				itemAU[count]=MPool_AllocEx(pPool, pPool->slabs[i]);
				count += 1;
			}
		}
		
		for(i=0; i<count; i++){
			MPool_FreeEx(pPool, itemAU[i]);
		}
	}
	STIMING_END(timing);
	STIMING_PRINT(timing, "Alloc & Free");
	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 2: \n%s\n", _gTest_MDump);

	
	/* Check GC */
	STIMING_BEG(timing);
	MPool_GC(pPool, 50);

	STIMING_END(timing);
	STIMING_PRINT(timing, "GC");
	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 3: \n%s\n", _gTest_MDump);

	STIMING_BEG(timing);
	for(k=0; k<100; k++){
		for(i=0, count=0; i<_TEST_MEM_GC; i++){
			for(j=0; j<alkCnt; j++){
				itemAU[count]=MPool_AllocEx(pPool, pPool->slabs[i]);
				count += 1;
			}
		}
		
		for(i=0; i<count; i++){
			MPool_FreeEx(pPool, itemAU[i]);
		}
	}
	STIMING_END(timing);
	STIMING_PRINT(timing, "Alloc & Free");
	/* Dump */
	MPool_Dump(pPool, _gTest_MDump, _TEST_MEM_DUMP_BUF);
	printf("\nDump 4: \n%s\n", _gTest_MDump);

	
	return 0;
}

typedef struct{
	unsigned short	port;
	unsigned short	reserv;
	unsigned int	ipAddr;
}_t_test_ipport;

static 	int _Test_MemAssign(_t_test_ipport * pIPPort)
{
	unsigned short	port;
	unsigned int 	ipAddr;


	ipAddr 	= pIPPort->ipAddr;
	port 	= pIPPort->port;

	printf("%08x - %04x\n", ipAddr, port);
	return 0;
}

#define _TEST_MEM_CPY_LEN 	0X10000
static 	int _Test_Memcpy(void)
{
	int i,j;
	unsigned int src[_TEST_MEM_CPY_LEN];
	unsigned int dst[_TEST_MEM_CPY_LEN];
	for(i=0; i<_TEST_MEM_CPY_LEN; i++){
		src[i] = 0X0100007F;
	}
	for(i=0; i<_TEST_MEM_CPY_LEN; i++){
		dst[i] = 0X00000000;
	}
	for(j=0; j<1000; j++){
		for(i=0; i<_TEST_MEM_CPY_LEN; i++){
			dst[i] = src[i];
		}
	}

	for(i=0; i<1000; i++){
		if(src[i] != 0X0100007F){
			printf("Mem Error: %d %p \n", i, src+i);
		}
	}

	for(i=0; i<1000; i++){
		if(dst[i] != 0X0100007F){
			printf("Mem Error: %d %p \n", i, dst+i);
		}
	}

	return 0;
}

int 	main(void)
{
	#if 0
	printf("Test Mem Simple 0:\n");
	_Test_Simple(0);

	printf("Test Mem Simple 1:\n");
	_Test_Simple(1);
	#endif

	#if 0
	printf("Test Mem Slab:\n");
	_Test_Slab(1000);
	#endif

	#if 0
	printf("Test Mem GC:\n");
	_Test_Gc(1000);
	#endif
	
	#if 0
	printf("Test Mem GN:\n");
	_Test_Gn(100);
	#endif

	_t_test_ipport tIPPort;
	
	tIPPort.ipAddr	= 0X01020304;
	tIPPort.port 	= 0XABCD;
	
	_Test_MemAssign(&tIPPort);
	return 0;
}



